use std::cell::UnsafeCell;
use std::sync::Arc;
use std::ops::Deref;
use std::alloc::Global;

pub struct Cp<T:?Sized> {
	_arc:Arc<UnsafeBuf>,
	data:*const T,
}

unsafe impl<T:?Sized> Send for Cp<T> {}
unsafe impl<T:?Sized> Sync for Cp<T> {}

pub trait MakeCp {
	fn make_const_slice<T>(&self,len:usize) -> Option<Cp<[T]>>;
	fn make_const_pointer<T>(&self) -> Option<Cp<T>>;
}

impl<T:?Sized> Cp<T> {
	pub unsafe fn new(arc:Arc<UnsafeBuf>,data:*const T) -> Self {
		Self {
			_arc:arc,
			data:data,
		}
	}
}

impl<T:?Sized> Deref for Cp<T> {
	type Target = T;
	fn deref(&self) -> &Self::Target {
		unsafe {
			&*self.data
		}
	}
}

pub struct UnsafeBuf {
	data:*mut [u8],
	cursor:UnsafeCell<usize>,
	alloc:Global,
}

impl UnsafeBuf {
	pub fn new(len:usize) -> Self {
		let (data,alloc) = unsafe { Box::into_raw_with_allocator(Box::new_uninit_slice(len).assume_init()) };
		Self {
			data:data,
			cursor:UnsafeCell::new(0),
			alloc:alloc,
		}
	}
	
	pub unsafe fn get(&self) -> &mut [u8] {
		&mut *self.data
	}
	
	
	pub fn get_mut(&mut self) -> &mut [u8] {
		unsafe { &mut *self.data }
	}
	
	pub fn rest(&self) -> &[u8] {
		unsafe { &(*self.data)[*self.cursor.get()..] }
	}
	
	pub fn cursor(&self) -> usize {
		unsafe { *self.cursor.get() }
	}
	
	pub unsafe fn cursor_mut(&self) -> &mut usize {
		&mut *self.cursor.get()
	}
	
}

impl MakeCp for Arc<UnsafeBuf> {
	fn make_const_slice<T>(&self,len:usize) -> Option<Cp<[T]>> {
		let last_cursor = unsafe {*self.cursor.get()};
		let next_cursor = last_cursor + len * std::mem::size_of::<T>();
		if next_cursor > self.data.len() { return None; }
		let mut_ref = unsafe { self.cursor_mut() };
		*mut_ref = next_cursor;
		unsafe {
			let slice = std::slice::from_raw_parts(&(*self.data)[last_cursor] as *const u8 as usize as *const T, len);
			Some(Cp::new(self.clone(),slice))
		}
	}
	
	fn make_const_pointer<T>(&self) -> Option<Cp<T>> {
		let last_cursor = unsafe {*self.cursor.get()};
		let next_cursor = last_cursor + std::mem::size_of::<T>();
		if next_cursor > self.data.len() { return None; }
		let mut_ref = unsafe { self.cursor_mut() };
		*mut_ref = next_cursor;
		unsafe {
			Some(Cp::new(self.clone(),&(*self.data)[last_cursor] as *const u8 as usize as *const T))
		}
	}
}
 
impl Deref for UnsafeBuf {
	type Target = [u8];
	fn deref(&self) -> &Self::Target {
		unsafe {
			&*self.data
		}
	}
}

impl Drop for UnsafeBuf {
	fn drop(&mut self) {
		unsafe { Box::from_raw_in(self.data, self.alloc); }
	}
}







